package com.proton.carepatchtemp.activity;

import android.app.ProgressDialog;
import android.content.Intent;
import android.graphics.Color;
import android.graphics.DashPathEffect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;

import com.apkfuns.logutils.LogUtils;
import com.github.mikephil.charting.charts.LineChart;
import com.github.mikephil.charting.components.Description;
import com.github.mikephil.charting.components.Legend;
import com.github.mikephil.charting.components.LimitLine;
import com.github.mikephil.charting.components.XAxis;
import com.github.mikephil.charting.components.YAxis;
import com.github.mikephil.charting.data.BarEntry;
import com.github.mikephil.charting.data.Entry;
import com.github.mikephil.charting.data.LineData;
import com.github.mikephil.charting.data.LineDataSet;
import com.github.mikephil.charting.formatter.IAxisValueFormatter;
import com.github.mikephil.charting.highlight.Highlight;
import com.github.mikephil.charting.interfaces.datasets.ILineDataSet;
import com.github.mikephil.charting.listener.OnChartValueSelectedListener;
import com.github.mikephil.charting.utils.MPPointF;
import com.google.gson.reflect.TypeToken;
import com.proton.carepatchtemp.R;
import com.proton.carepatchtemp.adapter.NotesAdapter;
import com.proton.carepatchtemp.base.BaseActivity;
import com.proton.carepatchtemp.constant.Codes;
import com.proton.carepatchtemp.constant.Config;
import com.proton.carepatchtemp.constant.Extras;
import com.proton.carepatchtemp.database.table.Note;
import com.proton.carepatchtemp.database.table.Report;
import com.proton.carepatchtemp.fragment.ShareReportFragment;
import com.proton.carepatchtemp.ui.ChartView.DayAxisValueFormatter;
import com.proton.carepatchtemp.ui.ChartView.MyAxisValueFormatter;
import com.proton.carepatchtemp.ui.ChartView.XYMarkerView;
import com.proton.carepatchtemp.utils.FileUtils;
import com.proton.carepatchtemp.utils.FormatUtils;
import com.proton.carepatchtemp.utils.JSONUtils;
import com.proton.carepatchtemp.utils.NetUtils;
import com.proton.carepatchtemp.utils.NumUtils;
import com.proton.carepatchtemp.utils.SpUtils;
import com.proton.carepatchtemp.utils.ThreadUtils;
import com.proton.carepatchtemp.utils.eventbus.MainEvent;
import com.proton.carepatchtemp.utils.net.ReportCenter;
import com.proton.carepatchtemp.utils.ui.ToastUtils;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class ReportDetailActivity extends BaseActivity implements OnChartValueSelectedListener {
    protected RectF mOnValueSelectedRectF = new RectF();
    private LinearLayoutManager mLinearLayoutManager;
    private NotesAdapter mNotesAdapter;
    private ProgressDialog mProgressDialog;
    private List<Note> mNotes = new ArrayList<>();
    private ArrayList<Entry> yVals1 = new ArrayList<>();
    private boolean hasRawData = false;
    private long reportId;
    private Handler mHandler = new Handler();
    private Report mReport;
    private Report.DataBean mDataBean;
    private float maxTempRpt;
    //  报告数据
    private float maxTemp = 0f;
    private YAxis mLeftAxis;
    private DayAxisValueFormatter mXAxisFormatter;
    private ImageButton mBtnBack;
    private ImageView mIvShareReport;
    private LineChart mLineChart;
    private FrameLayout mFrlAddNote;
    private RecyclerView mRcvReportNotesList;
    /**
     * --.--
     */
    private TextView mTvHighestTempRpt;
    /**
     * ℃
     */
    private TextView mTvReportUnit;
    /**
     * --分--秒
     */
    private TextView mTvAllTestTime;
    private TextView mTvRptTips;
    private ImageView mIvReportBigChart;

    @Override
    public void dealEvent(MainEvent event) {
        switch (event.getId()) {
            case Codes.REPORT_GET_NOTES:
                if (event.isSuccess()) {
                    if (null != event.getList() && 0 < event.getList().size()) {
                        mNotes.clear();
                        mNotes.addAll(event.getList());
                        mNotesAdapter.notifyDataSetChanged();
                    }
                } else {
                    ToastUtils.e(R.string.report_detial_get_notes_failed);
                }
                break;
            case Codes.REPORT_DELETE_NOTES:
                if (event.isSuccess()) {
                    if (0 >= mNotes.size()) {
                        ReportCenter.getCommentList(String.valueOf(reportId));
                    }
                    ToastUtils.s(R.string.delete_note_success);
                } else {
                    ToastUtils.e(R.string.delete_note_failed);
                }
                break;
            default:
                break;
        }
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_report_detail);
        // 判断无网络环境
        if (NetUtils.noNet()) {
            finish();
            return;
        }
        if (null == getIntent().getExtras()) {
            ToastUtils.e(R.string.get_rpt_info_failed);
        } else {
            mReport = (Report) getIntent().getExtras().getSerializable(Extras.REPORT);
            if (null == mReport) {
                ToastUtils.e(R.string.get_rpt_info_failed);
                finish();
            }
            reportId = mReport.getId();
            mDataBean = mReport.getData();
        }

        mProgressDialog = new ProgressDialog(this);
        mProgressDialog.setCancelable(true);
        mProgressDialog.setMessage(getString(R.string.loading));
        initView();
        setListener();
        try {
            initChart();
            setData();
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            mTvReportUnit.setText(" ℃");
        } else {
            mTvReportUnit.setText(" ℉");
        }

        mLinearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false);
        mNotesAdapter = new NotesAdapter(this, mNotes);
        mRcvReportNotesList.setLayoutManager(mLinearLayoutManager);
        mRcvReportNotesList.setAdapter(mNotesAdapter);
        mRcvReportNotesList.addItemDecoration(new DividerItemDecoration(this, DividerItemDecoration.VERTICAL));
        mTvAllTestTime.setText(FormatUtils.formatTime(mReport.getEndtime() - mReport.getStarttime()));

        if (mDataBean != null) {
            maxTempRpt = Float.parseFloat(mDataBean.getTemp_max());
        }

        if (NumUtils.withinTempRange(maxTempRpt)) {
            if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                mTvHighestTempRpt.setText(maxTempRpt + "");
            } else {
                mTvHighestTempRpt.setText(FormatUtils.c2F(maxTempRpt) + "");
            }
            if (25F <= maxTempRpt && maxTempRpt < 35.9F) {
                mTvRptTips.setText(R.string.report_detial_wait_normal);
            } else if (35.9F <= maxTempRpt && maxTempRpt < 37.2F) {
                mTvRptTips.setText(R.string.report_detial_normal);
            } else if (37.3F <= maxTempRpt && maxTempRpt < 38.0F) {

                if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                    mTvRptTips.setText(R.string.report_detial_low_fever_c);
                } else {
                    mTvRptTips.setText(R.string.report_detial_low_fever_f);
                }

            } else if (38.0F <= maxTempRpt && maxTempRpt < 39F) {

                if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                    mTvRptTips.setText(R.string.report_detial_fever_c);
                } else {
                    mTvRptTips.setText(R.string.report_detial_fever_f);
                }

            } else if (39F <= maxTempRpt && maxTempRpt < 42F) {
                mTvRptTips.setText(R.string.report_detial_high_fever);
            } else if (42F <= maxTempRpt && maxTempRpt <= 45F) {
                if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                    mTvRptTips.setText(R.string.report_detial_out_range_c);
                } else {
                    mTvRptTips.setText(R.string.report_detial_out_range_f);
                }

            }
        } else {
            if (maxTempRpt < 25F) {
                if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                    mTvHighestTempRpt.setText("< 25.00");
                } else {
                    mTvHighestTempRpt.setText("< 77.00");
                }
            } else if (maxTempRpt > 45F) {
                if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                    mTvHighestTempRpt.setText("> 45.00");
                } else {
                    mTvHighestTempRpt.setText("> 113.00");
                }
            }
            if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                mTvRptTips.setText(R.string.report_detial_out_range_c);
            } else {
                mTvRptTips.setText(R.string.report_detial_out_range_f);
            }
        }
    }

    private void initChart() {
        mLineChart.setOnChartValueSelectedListener(this);

        mLineChart.getDescription().setEnabled(false);
        //  禁止绘制点击柱状图后的标签
        mLineChart.setDrawMarkers(true);
        mLineChart.setPinchZoom(true);
        mLineChart.setScaleYEnabled(false);
        mLineChart.setScaleXEnabled(false);
        mLineChart.setDrawGridBackground(false);
        mLineChart.setDoubleTapToZoomEnabled(false);

        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            mLineChart.setVisibleYRange(30F, 42F, YAxis.AxisDependency.LEFT);
        } else {
            mLineChart.setVisibleYRange(86F, 107.6F, YAxis.AxisDependency.LEFT);
        }

        mLineChart.setDrawBorders(false);
        mLineChart.animateX(1000);
        mLineChart.setNoDataText(getString(R.string.have_no_data));

        XAxis xAxis = mLineChart.getXAxis();
        xAxis.setPosition(XAxis.XAxisPosition.BOTTOM);
        xAxis.setLabelCount(5);
        mXAxisFormatter = new DayAxisValueFormatter(mLineChart);
        mXAxisFormatter.setStartTime(mReport.getStarttime());
        xAxis.setValueFormatter(mXAxisFormatter);
        xAxis.enableGridDashedLine(10f, 10f, 0f);

        IAxisValueFormatter custom = new MyAxisValueFormatter();

        mLeftAxis = mLineChart.getAxisLeft();

        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
            mLeftAxis.setAxisMinimum(30.0F);
            mLeftAxis.setAxisMaximum(42.0F);
        } else {
            mLeftAxis.setAxisMinimum(86.0F);
            mLeftAxis.setAxisMaximum(107.6F);
        }

        mLeftAxis.setValueFormatter(custom);
        mLeftAxis.setPosition(YAxis.YAxisLabelPosition.OUTSIDE_CHART);
        mLeftAxis.setSpaceTop(15f);
        mLeftAxis.enableGridDashedLine(10f, 10f, 0f);
        YAxis rightAxis = mLineChart.getAxisRight();
        rightAxis.setEnabled(false);

        Legend l = mLineChart.getLegend();
        l.setEnabled(false);

    }

    private void setData() {
        mProgressDialog.show();

        ThreadUtils.runOnOtherThread(() -> {
            String fpString;
            JSONObject fpJsonObj;
            if (!FileUtils.getJson_filepath().contains(FileUtils.json_filepath + File.separator + reportId)) {
                LogUtils.e("have no filePath");
                if (TextUtils.isEmpty(mReport.getFilepath())) {
                    runOnUiThread(() -> {
                        mProgressDialog.dismiss();
                        ToastUtils.e("数据异常");
                    });
                    return;
                }
                fpString = FileUtils.downLoadFromUrl(mReport.getFilepath(), String.valueOf(mReport.getId()), FileUtils.json_filepath);
            } else {
                try {
                    fpString = FileUtils.readJSONFile(FileUtils.json_filepath, mReport.getId());
                } catch (IOException e) {
                    e.printStackTrace();
                    fpString = null;
                    return;
                }
            }


            //  第一阶段文件转换为JSON对象
            try {
                fpJsonObj = new JSONObject(fpString);
            } catch (JSONException e) {
                fpJsonObj = null;
                e.printStackTrace();
            }

            if (null == fpJsonObj) {
                LogUtils.d("Load file failed ! Please retry!");
                mLineChart.setNoDataText(getString(R.string.string_load_fail));
                FileUtils.deleteFile(FileUtils.json_filepath, String.valueOf(mReport.getId()));
                mHandler.post(() -> {
                    mProgressDialog.dismiss();
                    if (null != mLineChart.getData()) {
                        mLineChart.getData().notifyDataChanged();
                        mLineChart.notifyDataSetChanged();
                    }
                    mLineChart.invalidate();
                });
                return;
            }

            yVals1.clear();
//            colors.clear();
            //是否包含RawData字段
            hasRawData = fpJsonObj.has(Extras.RPT_RAW_DATA);

            JSONArray array = null;
            try {
                array = fpJsonObj.getJSONArray(Extras.RPT_FLOATS);
            } catch (JSONException e) {
                e.printStackTrace();
            }

            //设置报警线
            float high = SpUtils.getFloat(Extras.WARNING_HIGHEST_TEMP, 37.5F);
            float low = SpUtils.getFloat(Extras.WARNING_LOWEST_TEMP, 35.0F);
            try {
                high = (float) fpJsonObj.getDouble(Extras.RPT_ALERT_MAX);
            } catch (JSONException e) {
                e.printStackTrace();
                high = SpUtils.getFloat(Extras.WARNING_HIGHEST_TEMP, 37.5F);
            }

            try {
                low = (float) fpJsonObj.getDouble(Extras.RPT_ALERT_MIN);
            } catch (JSONException e) {
                e.printStackTrace();
                low = SpUtils.getFloat(Extras.WARNING_LOWEST_TEMP, 35.0F);
            }
            LimitLine limitLine;
            if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                limitLine = new LimitLine(37.2F, 37.2F + "℃");
            } else {
                limitLine = new LimitLine(98.96F, 98.96F + "℉");
            }


            limitLine.setTextSize(10f);
            limitLine.setLineWidth(2f);
            limitLine.enableDashedLine(10f, 10f, 0f);

            limitLine.setTextColor(ContextCompat.getColor(this, R.color.orange));
            limitLine.setLineColor(ContextCompat.getColor(this, R.color.orange));


            mLeftAxis.addLimitLine(limitLine);


            List<Float> list = new ArrayList<>();
            list.clear();
            Type listType = new TypeToken<ArrayList<Float>>() {
            }.getType();

            list = JSONUtils.getObj(array.toString(), listType, "yyyy-MM-dd");
            LogUtils.json(array.toString());
            LogUtils.d(list);

            if (null != list) {
                maxTemp = Collections.max(list);
                for (int i = 1; i <= list.size(); i++) {
                    //空保护必要
                    if (null != list.get(i - 1)) {
                        float val = list.get(i - 1);
                        if (1 == SpUtils.getInt(Extras.TEMP_UNIT, Config.TEMP_UNIT_DEFAULT)) {
                            yVals1.add(new BarEntry(i, val));
                        } else {
                            yVals1.add(new BarEntry(i, FormatUtils.c2F(val)));
                        }
                    }
                }
            }

//            BarDataSet set1;
            LineDataSet set1;
            if (mLineChart.getData() != null &&
                    mLineChart.getData().getDataSetCount() > 0) {
                set1 = (LineDataSet) mLineChart.getData().getDataSetByIndex(0);
                set1.setValues(yVals1);

                mLineChart.getData().notifyDataChanged();
                mLineChart.notifyDataSetChanged();
            } else {
                set1 = new LineDataSet(yVals1, "The year 2017");
//            set1.setColors(ColorTemplate.MATERIAL_COLORS);
                set1.setDrawFilled(true);
                set1.setDrawCircles(false);
                set1.disableDashedLine();
//                set1.enableDashedLine(10f, 5f, 0f);
                set1.enableDashedHighlightLine(10f, 5f, 0f);
                set1.setColor(Color.TRANSPARENT);
                set1.setCircleColor(Color.BLACK);
                set1.setLineWidth(0f);
//                set1.setCircleRadius(3f);
                set1.setDrawCircleHole(false);
                set1.setDrawValues(false);
//                set1.setValueTextSize(9f);
                set1.setDrawFilled(true);
                set1.setFormLineWidth(1f);
                set1.setFormLineDashEffect(new DashPathEffect(new float[]{10f, 5f}, 0f));
                set1.setFormSize(15.f);

//                ArrayList<IBarDataSet> dataSets = new ArrayList<IBarDataSet>();
//                dataSets.add(set1);
                ArrayList<ILineDataSet> dataSets = new ArrayList<ILineDataSet>();
                dataSets.add(set1); // add the datasets


                Drawable drawable = ContextCompat.getDrawable(this, R.drawable.line_chart);
                drawable.setAlpha(Config.CHART_ALPHA);
                set1.setFillDrawable(drawable);

//                BarData data = new BarData(dataSets);
//                data.setValueTextSize(10f);
////            data.setValueTypeface(mTfLight);
//                data.setBarWidth(0.9f);
//                data.setDrawValues(false);
                LineData data = new LineData(dataSets);
                data.setDrawValues(false);
                mProgressDialog.dismiss();
                mLineChart.setData(data);

                if (maxTemp < 30) {
                    Description description = new Description();
                    description.setText(getString(R.string.string_out_of_range_temp));
                    mLineChart.setDescription(description);
                } else {
                    mLineChart.setDescription(null);
                }

//
//                //保存图片，留作pdf生成时使用
//                Bitmap b = mLineChart.getChartBitmap();
//
//                FileOutputStream stream = null;
//                try {
//                    stream = new FileOutputStream(FileUtils.getReport() + File.separator + reportId
//                            + ".png");
//            /*
//             * Write bitmap to file using JPEG or PNG and 40% quality hint for
//             * JPEG.
//             */
//                    b.compress(Bitmap.CompressFormat.PNG, 40, stream);
//                    stream.flush();
//                    stream.close();
//                } catch (Exception e) {
//                    e.printStackTrace();
//                }
                mHandler.post(() -> {
                    XAxis xAxis = mLineChart.getXAxis();
                    if (hasRawData) {
                        mXAxisFormatter = new DayAxisValueFormatter(mLineChart);
                    } else {
                        mXAxisFormatter = new DayAxisValueFormatter(mLineChart, 8000L);
                    }
                    mXAxisFormatter.setStartTime(mReport.getStarttime());
                    xAxis.setValueFormatter(mXAxisFormatter);

                    XYMarkerView mv = new XYMarkerView(this, mXAxisFormatter);
                    mv.setStartTime(mReport.getStarttime());
                    mv.setChartView(mLineChart); // For bounds control
                    mLineChart.setMarker(mv); // Set the marker to the chart

                    if (null != mLineChart.getData()) {
                        mLineChart.getData().notifyDataChanged();
                        mLineChart.notifyDataSetChanged();
                    }
                    mLineChart.invalidate();
                });
//                mLineChart.invalidate();
            }

        });


    }

    @Override
    protected void onStart() {
        super.onStart();
        initData();
    }

    private void initData() {
        ThreadUtils.runOnOtherThread(() -> {
            ReportCenter.getCommentList(reportId + "");
        });
    }

    @Override
    protected void setListener() {
        mBtnBack.setOnClickListener(view -> {
            finish();
        });

        mFrlAddNote.setOnClickListener(view -> {
            Intent addNote = new Intent(ReportDetailActivity.this, AddNoteActivity.class);
            addNote.putExtra(Extras.REPORTID, reportId);
            startActivity(addNote);
        });

        mIvShareReport.setOnClickListener(v -> {
            ShareReportFragment shareReportFragment = new ShareReportFragment();
            shareReportFragment.setReport(mReport);
            shareReportFragment.show(getSupportFragmentManager(), String.valueOf(reportId));
        });

        mIvReportBigChart.setOnClickListener(v -> {
            Intent goBigChart = new Intent(ReportDetailActivity.this, ReportBigChartActivity.class);
            Bundle bundle = new Bundle();
            bundle.putSerializable(Extras.REPORT, mReport);
            goBigChart.putExtras(bundle);
            startActivity(goBigChart);
        });
    }

    @Override
    public void onEventMainThread(MainEvent event) {
        dealOnEvent(event);
    }

    private void initView() {
        mBtnBack = findViewById(R.id.btn_back);
        mIvShareReport = findViewById(R.id.iv_share_report);
        mLineChart = findViewById(R.id.bc_report_chart);
        mFrlAddNote = findViewById(R.id.frl_add_note);
        mRcvReportNotesList = findViewById(R.id.rcv_report_notes_list);
        mTvHighestTempRpt = findViewById(R.id.tv_highest_temp_rpt);
        mTvReportUnit = findViewById(R.id.tv_report_unit);
        mTvAllTestTime = findViewById(R.id.tv_all_test_time);
        mTvRptTips = findViewById(R.id.tv_rpt_tips);
        mIvReportBigChart = findViewById(R.id.iv_report_big_chart);
    }

    @Override
    public void onValueSelected(Entry e, Highlight h) {
        if (e == null)
            return;

        RectF bounds = mOnValueSelectedRectF;
        MPPointF position = mLineChart.getPosition(e, YAxis.AxisDependency.LEFT);

        Log.i("bounds", bounds.toString());
        Log.i("position", position.toString());

        LogUtils.i("x-index",
                "low: " + mLineChart.getLowestVisibleX() + ", high: "
                        + mLineChart.getHighestVisibleX());

        MPPointF.recycleInstance(position);
    }

    @Override
    public void onNothingSelected() {

    }
}
